package com.dogcatfishdish.containers
{
	import flash.display.DisplayObjectContainer;
	import flash.events.EventDispatcher;
	
	import uk.co.misterbenn.errors.ScreenManagerError;
	import uk.co.misterbenn.events.ScreenEvent;
	
	public class ScreenManager extends EventDispatcher implements IScreenManager
	{
		protected var _screenSequence:Array = [];
		protected var _screen:IScreen;
		protected var _view:DisplayObjectContainer;
		protected var _index:int = -1;
		protected var _onCompleted:Function;
		protected var _onChanged:Function;

		/**
		 * Creates a new ScreenManager instance.
		 *  
		 * @param view A DisplayObjectContainer that the screens will be attached to.
		 * 
		 */		
		public function ScreenManager(view:DisplayObjectContainer = null)
		{
			_view = view;	
		}
		
		//public methods
		
		/**
		 * @inheritDoc
		 */	
		public function get view():DisplayObjectContainer
		{
			if(!_view)
				throw new ScreenManagerError(ScreenManagerError.NO_VIEW);
				
			return _view;
		}
		
		/**
		 * @inheritDoc
		 */	
		public function set view(value:DisplayObjectContainer):void
		{
			_view = value;	
		}
		
		/**
		 * @inheritDoc
		 */		
		public function set onCompleted(func:Function):void
		{
			_onCompleted = func;
		}
		
		/**
		 * @inheritDoc
		 */	
		public function set onChanged(func:Function):void
		{
			_onChanged = func;
		}
		
		/**
		 * @inheritDoc
		 */	
		public function addScreens(...params):void
		{
			var len:uint = params.length;
			for(var i:uint = 0; i < len; ++i)
			{
				var screen:IScreen = params[i];
				
				if(screen == null)
					throw new ScreenManagerError(ScreenManagerError.WRONG_TYPE);
				
				screen.context = this;
				
				_screenSequence.push(screen);	
			}	
		}
		
		/**
		 * @inheritDoc 
		 */		
		public function removeScreen(screen:IScreen):void
		{
			var len:uint = _screenSequence.length;
			for(var i:uint = 0; i < len; ++i)
			{
				var screenObj:IScreen = _screenSequence[i];
				
				if(screen == screenObj)
					_screenSequence.splice(i, 1);
			}
		}
		
		/**
		 * @inheritDoc
		 */	
		public function nextScreen():void
		{
			_index++;
			
			if(_index >= _screenSequence.length)
			{
				applyCallback(_onCompleted);
				dispatchEvent(new ScreenEvent(ScreenEvent.COMPLETED, _index));
				return;
			}
	
			changeScreen();
		}
		
		/**
		 * @inheritDoc
		 */	
		public function previousScreen():void
		{
			if(_index == 0)
				return;
				
			_index--;
			
			changeScreen();
		}
		
		
		///protected methods
		protected function changeScreen():void
		{
			clearPreviousScreen();
			
			initialiseScreen();	

			applyCallback(_onChanged, _index);
			
			dispatchEvent(new ScreenEvent(ScreenEvent.CHANGED, _index));
		}
		
		protected function initialiseScreen():void
		{
			_screen = _screenSequence[_index];
			_screen.add();
			
			view.addChild(_screen.content);
		}
		
		protected function clearPreviousScreen():void
		{
			if(_screen == null) 
				return;
			
			if(_view.contains(_screen.content))
			{
				_screen.remove();
				_view.removeChild(_screen.content);
			}	
		}
		
		protected function applyCallback(func:Function, ...params):void
		{
			if(func != null)
				func.apply(null, params);
		}
		

	}
}